
#ifndef _TTG_EXTRAS_FUNCTIONS_
#define _TTG_EXTRAS_FUNCTIONS_
#include "Common/Definitions.h"

#include "Operations.h"

namespace ttg_internal
{
	//Implements "DRAND" function (which generates random float).
	class DRandOperation :public ttg::extras::Operation<float>
	{
		private:
			ttg::extras::Operation<float> *lower;
			ttg::extras::Operation<float> *upper;
		public:
			//Creates operation.
			inline DRandOperation(ttg::extras::Operation<float> *lower, ttg::extras::Operation<float> *upper)
			{
				this->lower = lower;
				this->upper = upper;
			}
			//Returns random float.
			virtual float calculate()
			{
				float l = lower->calculate();
				float multiplier = upper->calculate() - l; 
				return ((float)rand() / RAND_MAX) * multiplier + l;
			}
			//Operation member.
			virtual bool isStatic()
					{ return false; }
			~DRandOperation()
			{
				SAFE_DELETE(lower);
				SAFE_DELETE(upper);
			}
			//Creates operation with given sources. In case of error returns NULL.
			virtual OperationInfo *createInstance(OperationInfo *s1,
												  OperationInfo *s2,
												  OperationInfo *s3)
			{
				ttg::extras::Operation<float> *op1 = dynamic_cast<Operation<float> *>(s1);
				ttg::extras::Operation<float> *op2 = dynamic_cast<Operation<float> *>(s2);
				if (op1 == NULL || op2 == NULL)
					return NULL;
				else
					return new DRandOperation(op1, op2);
			}
	};

	//Implements "VRAND" function (which generates random vector).
	class VRandOperation :public ttg::extras::Operation<ttg::math::vec3f>
	{
		private:
			ttg::extras::Operation<ttg::math::vec3f> *lower;
			ttg::extras::Operation<ttg::math::vec3f> *upper;
		public:
			//Creates operation.
			inline VRandOperation(ttg::extras::Operation<ttg::math::vec3f> *lower,
								  ttg::extras::Operation<ttg::math::vec3f> *upper)
			{
				this->lower = lower;
				this->upper = upper;
			}
			//Returns random vec3f.
			virtual ttg::math::vec3f calculate()
			{
				ttg::math::vec3f l = lower->calculate();
				ttg::math::vec3f multiplier = upper->calculate() - l; 
				return ttg::math::vec3f(((float)rand() / RAND_MAX) * multiplier.x + l.x,
										((float)rand() / RAND_MAX) * multiplier.y + l.y,
										((float)rand() / RAND_MAX) * multiplier.z + l.z);
			}
			//Operation member.
			virtual bool isStatic()
					{ return false; }
			~VRandOperation()
			{
				SAFE_DELETE(lower);
				SAFE_DELETE(upper);
			}
			//Creates operation with given sources. In case of error returns NULL.
			virtual OperationInfo *createInstance(OperationInfo *s1,
												  OperationInfo *s2,
												  OperationInfo *s3)
			{
				ttg::extras::Operation<ttg::math::vec3f> *op1 
							= dynamic_cast<ttg::extras::Operation<ttg::math::vec3f> *>(s1);
				ttg::extras::Operation<ttg::math::vec3f> *op2
							= dynamic_cast<ttg::extras::Operation<ttg::math::vec3f> *>(s2);
				if (op1 == NULL || op2 == NULL)
					return NULL;
				else
					return new VRandOperation(op1, op2);
			}
	};
}

#endif
